home *** CD-ROM | disk | FTP | other *** search
- /*
- File: OTPingSample.c
-
- Contains: A trivial ping implementation.
-
- Written by: Quinn "The Eskimo!"
-
- Copyright: © 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- #include <stdio.h>
- #include <OpenTransport.h>
- #include <OpenTptInternet.h>
-
- /////////////////////////////////////////////////////////////////////
-
- static UInt16 ChecksumBuffer(UInt16* buf, size_t len)
- {
- // This checksum implementation requires the buffer to be an even number of bytes long.
- UInt32 sum;
- size_t nwords;
-
- nwords = len / 2;
- sum = 0;
- while (nwords > 0) {
- sum += *buf;
- buf++;
- nwords -= 1;
- }
- sum = (sum >> 16 ) + (sum & 0xffff);
- sum += (sum >> 16);
-
- return ~sum;
- }
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus CreateAndConfigICMP(EndpointRef *ep)
- {
- OSStatus err;
-
- *ep = OTOpenEndpoint(OTCreateConfiguration(kRawIPName), 0, nil, &err);
-
- if (err == noErr) {
- err = OTBind(*ep, nil, nil);
-
- // no others options to negotiate at this stage
-
- // You might think we need to negotiate the XTI_GENERIC/XTI_PROTOTYPE
- // option to request ICMP packets (ie protocol 2). This is not
- // necessary because rawip endpoints default to that protocol.
- }
-
- return (err);
- }
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus LookupName(InetSvcRef inet_services, char *host_name, InetHost *host_addr)
- {
- OSStatus err;
- InetHostInfo response;
-
- memset(&response, 0, sizeof(response));
-
- err = OTInetStringToAddress(inet_services, host_name, &response);
-
- if (err == noErr) {
- *host_addr = response.addrs[0];
- }
-
- return (err);
- }
-
- /////////////////////////////////////////////////////////////////////
-
- enum {
- kOurMagic = 'Quin'
- };
-
- struct PingPacket {
- UInt8 pType;
- UInt8 pCode;
- UInt16 pChecksum;
- UInt16 pID;
- UInt16 pSeqNum;
- OSType pMagic;
- };
- typedef struct PingPacket PingPacket, *PingPacketPtr;
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus SendICMP(EndpointRef ep, InetHost dest, UInt16 seq_number)
- {
- OSStatus err;
- InetAddress dest_addr;
- TUnitData udata;
- PingPacket ping_data;
-
- OTInitInetAddress(&dest_addr, 0, dest);
-
- ping_data.pType = 8;
- ping_data.pCode = 0;
- ping_data.pChecksum = 0; // dummy checksum of 0 for purposes of checksum calculation
- ping_data.pID = 666;
- ping_data.pSeqNum = seq_number;
- ping_data.pMagic = kOurMagic;
-
- ping_data.pChecksum = ChecksumBuffer((UInt16 *) &ping_data, sizeof(ping_data));
-
- udata.addr.len = sizeof(dest_addr);
- udata.addr.buf = (unsigned char *) &dest_addr;
-
- udata.opt.len = 0;
- udata.opt.buf = nil;
-
- udata.udata.len = sizeof(ping_data);
- udata.udata.buf = (UInt8 *) &ping_data;
-
- err = OTSndUData(ep, &udata);
-
- return (err);
- }
-
- /////////////////////////////////////////////////////////////////////
-
- // we use this buffer to hold incoming ICMP packets
-
- static UInt8 icmp_data[5000];
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus WaitAndPrintICMPs(EndpointRef ep, UInt16 seq_number, Boolean *got_response)
- {
- TUnitData udata;
- long start_time;
- OSStatus err;
- InetAddress src_addr;
- PingPacketPtr ping_data_ptr;
-
- *got_response = false;
-
- start_time = TickCount();
-
- // Wait for 5 seconds and print out any ICMP packets we get back.
-
- do {
-
- // Set up the received...
-
- udata.addr.buf = (UInt8*) &src_addr;
- udata.addr.maxlen = sizeof(struct InetAddress);
- udata.opt.buf = nil;
- udata.opt.maxlen = 0;
- udata.udata.buf = icmp_data;
- udata.udata.maxlen = sizeof(icmp_data);
-
- // Look for a packet...
-
- err = OTRcvUData(ep, &udata, nil);
- if (err == noErr) {
- // Print out salient information from the packet...
- printf("•••Got ICMP!•••\n");
-
- printf("ICMP from = %d.%d.%d.%d\n", icmp_data[12], icmp_data[13], icmp_data[14], icmp_data[15]);
-
- ping_data_ptr = (PingPacketPtr) &icmp_data[20];
-
- printf("ICMP type = %d\n", ping_data_ptr->pType);
- printf("ICMP code = %d\n", ping_data_ptr->pCode);
-
- if (ping_data_ptr->pType == 0
- && ping_data_ptr->pID == 666
- && ping_data_ptr->pSeqNum == seq_number
- && ping_data_ptr->pMagic == kOurMagic) {
- *got_response = true;
- }
-
- fflush(stdout);
- } else if (err == kOTNoDataErr) {
- err = noErr;
- }
- } while (err == noErr && TickCount() < start_time + 5 * 60);
-
- return (err);
- }
-
- /////////////////////////////////////////////////////////////////////
-
- static OSStatus DoPing(InetHost dest)
- {
- OSStatus err;
- EndpointRef icmp_ep = nil;
- UInt16 seq_number;
- UInt16 lost;
- Boolean got_response;
-
- // Create the endpoint and negotiate the options...
- err = CreateAndConfigICMP(&icmp_ep);
-
- // Do the main ping loop...
-
- seq_number = 0;
- lost = 0;
- do {
- printf("\nSending ping...\n");
- err = SendICMP(icmp_ep, dest, seq_number);
- if (err == noErr) {
- err = WaitAndPrintICMPs(icmp_ep, seq_number, &got_response);
- }
- if (err == noErr) {
- if (!got_response) {
- lost += 1;
- }
- seq_number += 1;
- }
- } while (err == noErr && seq_number < 5);
-
- if (err == noErr) {
- printf("Ping complete. %d packets sent. %d packets lost. %d%% packet loss.\n", seq_number, lost, lost * 100 / seq_number);
- }
-
- // clean up
- if (icmp_ep != nil) {
- (void) OTCloseProvider(icmp_ep);
- }
- return err;
- }
-
- /////////////////////////////////////////////////////////////////////
-
- void main(void) {
- OSStatus err;
- char host_name[256];
- InetHost host_addr;
- InetSvcRef inet_services = nil;
-
- printf("Hello Cruel World!\n");
-
- err = InitOpenTransport();
-
- if (err == noErr) {
- inet_services = OTOpenInternetServices(kDefaultInternetServicesPath, 0, &err);
-
- if (err == noErr) {
- printf("Enter name of host to ping:\n");
- gets(host_name);
-
- err = LookupName(inet_services, host_name, &host_addr);
- }
-
- if (err == noErr) {
- err = DoPing(host_addr);
- }
-
- if (inet_services != nil) {
- OTCloseProvider(inet_services);
- }
-
- CloseOpenTransport();
- }
-
- if (err == noErr) {
- printf("Success!\n");
- } else {
- printf("Failure! Error = %d.\n", err);
- }
- printf("Done. Press command-Q to Quit.\n");
- }